added Feb 2001 SDK
[windows-sources.git] / shared source / sscli20 / jscript / engine / methodinvoker.cs
blobe29ca3e137b138b82506eb6d5edd93151eff04e9
1 // ==++==
2 //
3 //
4 // Copyright (c) 2006 Microsoft Corporation. All rights reserved.
5 //
6 // The use and distribution terms for this software are contained in the file
7 // named license.txt, which can be found in the root of this distribution.
8 // By using this software in any fashion, you are agreeing to be bound by the
9 // terms of this license.
10 //
11 // You must not remove this notice, or any other, from this software.
12 //
13 //
14 // ==--==
16 namespace Microsoft.JScript {
17 using System;
18 using System.Collections;
19 using System.Reflection;
20 using System.Reflection.Emit;
21 using System.Security;
22 using System.Security.Permissions;
23 using System.Threading;
24 using System.Diagnostics;
26 public abstract class MethodInvoker{
28 #if !DEBUG
29 [DebuggerStepThroughAttribute]
30 [DebuggerHiddenAttribute]
31 #endif
32 public abstract Object Invoke(Object thisob, Object[] parameters);
35 private static SimpleHashtable invokerFor = new SimpleHashtable(64);
36 private static int count = 0;
38 private static bool DoesCallerRequireFullTrust(MethodInfo method){
39 Assembly assembly = method.DeclaringType.Assembly;
40 // strongly-named assembly requires full trust or AllowPartiallyTrustedCallersAttribute to be called
41 FileIOPermission pathDiscoveryPermission = new FileIOPermission(PermissionState.None);
42 pathDiscoveryPermission.AllFiles = FileIOPermissionAccess.PathDiscovery;
43 pathDiscoveryPermission.Assert();
44 byte[] key = assembly.GetName().GetPublicKey();
45 if (key == null || key.Length == 0)
46 return false;
47 if (CustomAttribute.GetCustomAttributes(assembly, typeof(AllowPartiallyTrustedCallersAttribute), true).Length != 0)
48 return false;
49 return true;
52 internal static MethodInvoker GetInvokerFor(MethodInfo method){
53 // .NET security does not allow Deny, Assert or PermitOnly to be called via
54 // Reflection. We are effectively creating our own Reflection layer, so
55 // we must do the same thing.
56 if (method.DeclaringType == typeof(System.Security.CodeAccessPermission) && (method.Name == "Deny" || method.Name == "Assert" || method.Name == "PermitOnly"))
57 throw new JScriptException(JSError.CannotCallSecurityMethodLateBound);
59 MethodInvoker invoker = MethodInvoker.invokerFor[method] as MethodInvoker;
60 if (invoker != null) return invoker;
61 if (!SafeToCall(method)) return null;
62 bool requiresDemand = DoesCallerRequireFullTrust(method);
63 lock(MethodInvoker.invokerFor){
64 invoker = MethodInvoker.invokerFor[method] as MethodInvoker;
65 if (invoker != null) return invoker;
66 invoker = MethodInvoker.SpitAndInstantiateClassFor(method, requiresDemand);
67 MethodInvoker.invokerFor[method] = invoker;
69 return invoker;
72 private static bool SafeToCall(MethodInfo meth){
73 Type t = meth.DeclaringType;
74 return (
75 t != null
76 && t != typeof(System.Activator)
77 && t != typeof(System.AppDomain)
78 && t != typeof(System.IO.IsolatedStorage.IsolatedStorageFile)
79 && t != typeof(System.Reflection.Emit.MethodRental)
80 && t != typeof(System.Security.SecurityManager)
81 && !typeof(System.Reflection.Assembly).IsAssignableFrom(t)
82 && !typeof(System.Reflection.MemberInfo).IsAssignableFrom(t)
83 && !typeof(System.Resources.ResourceManager).IsAssignableFrom(t)
84 && !typeof(System.Delegate).IsAssignableFrom(t)
85 && (t.Attributes & TypeAttributes.HasSecurity) == 0
86 && (meth.Attributes & MethodAttributes.HasSecurity) == 0
87 && (meth.Attributes & MethodAttributes.PinvokeImpl) == 0
88 );
91 [ReflectionPermission(SecurityAction.Assert, Unrestricted = true)]
92 private static MethodInvoker SpitAndInstantiateClassFor(MethodInfo method, bool requiresDemand){
93 TypeBuilder tb = Runtime.ThunkModuleBuilder.DefineType("invoker"+MethodInvoker.count++, TypeAttributes.Public, typeof(MethodInvoker));
94 MethodBuilder mb = tb.DefineMethod("Invoke", MethodAttributes.Public|MethodAttributes.Virtual|MethodAttributes.ReuseSlot,
95 typeof(Object), new Type[]{typeof(Object), typeof(Object[])});
97 if (requiresDemand)
98 mb.AddDeclarativeSecurity(SecurityAction.Demand, new NamedPermissionSet("FullTrust"));
99 #if !DEBUG
100 mb.SetCustomAttribute(new CustomAttributeBuilder(Runtime.TypeRefs.debuggerStepThroughAttributeCtor, new Object[]{}));
101 mb.SetCustomAttribute(new CustomAttributeBuilder(Runtime.TypeRefs.debuggerHiddenAttributeCtor, new Object[]{}));
102 #endif
103 ILGenerator il = mb.GetILGenerator();
104 if (!method.DeclaringType.IsPublic)
105 method = method.GetBaseDefinition();
106 Type obT = method.DeclaringType;
107 if (!method.IsStatic){
108 il.Emit(OpCodes.Ldarg_1);
109 if (obT.IsValueType){
110 Convert.EmitUnbox(il, obT, Type.GetTypeCode(obT));
111 Convert.EmitLdloca(il, obT);
112 }else{
113 il.Emit(OpCodes.Castclass, obT);
116 ParameterInfo[] parameters = method.GetParameters();
117 LocalBuilder[] outTemps = null;
118 for (int i = 0, n = parameters.Length; i < n; i++){
119 il.Emit(OpCodes.Ldarg_2);
120 ConstantWrapper.TranslateToILInt(il, i);
121 Type pt = parameters[i].ParameterType;
122 if (pt.IsByRef){
123 pt = pt.GetElementType();
124 if (outTemps == null) outTemps = new LocalBuilder[n];
125 outTemps[i] = il.DeclareLocal(pt);
126 il.Emit(OpCodes.Ldelem_Ref);
127 if (pt.IsValueType)
128 Convert.EmitUnbox(il, pt, Type.GetTypeCode(pt));
129 il.Emit(OpCodes.Stloc, outTemps[i]);
130 il.Emit(OpCodes.Ldloca, outTemps[i]);
131 }else{
132 il.Emit(OpCodes.Ldelem_Ref);
133 if (pt.IsValueType)
134 Convert.EmitUnbox(il, pt, Type.GetTypeCode(pt));
137 if (!method.IsStatic && method.IsVirtual && !method.IsFinal && (!obT.IsSealed || !obT.IsValueType))
138 il.Emit(OpCodes.Callvirt, method);
139 else
140 il.Emit(OpCodes.Call, method);
141 Type rt = method.ReturnType;
142 if (rt == typeof(void))
143 il.Emit(OpCodes.Ldnull);
144 else if (rt.IsValueType)
145 il.Emit(OpCodes.Box, rt);
146 if (outTemps != null){
147 for (int i = 0, n = parameters.Length; i < n; i++){
148 LocalBuilder loc = outTemps[i];
149 if (loc != null){
150 il.Emit(OpCodes.Ldarg_2);
151 ConstantWrapper.TranslateToILInt(il, i);
152 il.Emit(OpCodes.Ldloc, loc);
153 Type pt = parameters[i].ParameterType.GetElementType();
154 if (pt.IsValueType)
155 il.Emit(OpCodes.Box, pt);
156 il.Emit(OpCodes.Stelem_Ref);
160 il.Emit(OpCodes.Ret);
161 Type t = tb.CreateType();
162 return (MethodInvoker)Activator.CreateInstance(t);